/*
 * Cree les cases du damiers
 */
package tp2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Serializable;
import javax.swing.JPanel;

/******************************************************************************
 *******************************Cases******************************************
 ******************************************************************************/
/**
 *Cette classe crée les cases du damier et gère la posisition de celle-ci en plus
 * de contenir les méthodes permettant voler le pions adverses et de la gestion
 * des évènements sur le damier.
 */
public class Cases extends JPanel implements Serializable {

    private boolean isCouleur; // Decide la couleur de la case
    private Color couleur; // Est la couleur de la case
    private Pions pion; // Pions
    private Jeu jeu; //Jeu
    private int no; //Numero du pion 0-63

    /**
     * Constructeur des cases général
     */
    public Cases(Jeu jeu, boolean couleur, int no) {
        this(jeu, couleur, 0, no);
    }

    /**
     * Constructeur des cases
     */
    public Cases(Jeu jeu, boolean couleur, int pionProprio, int no) {
        super(new GridLayout(1, 1));
        this.jeu = jeu;
        this.pion = new Pions(pionProprio, this);
        this.isCouleur = couleur;
        this.no = no;

        this.add(pion);
        pion.setVisible(false);

        this.setCouleur();

        this.addMouseListener(new GererEvenement());
    }

    /**
     * Set le propriétaire du pion
     * @param proprio Propriétaire du pion
     */
    public void setPionProprio(int proprio) {
        if (this.pion.isVisible()) {
            this.pion.setProprio(proprio);
        }
    }

    /**
     * initialise la case selon le joueur
     * @param proprio Propriétaire du pion
     */
    public void initCaseJoueur(int proprio) {
        this.togglePion();
        this.setPionProprio(proprio);
    }

    /**
     * Met le pion visible lorsque le joueur initialise la case
     */
    public void togglePion() {
        this.pion.setVisible(!this.pion.isVisible());
    }

    /**
     * Désélectionner le pion si il est sélectionné
     */
    public void unSelect() {
        if (this.pion.isSelected()) {
            this.toggleClick();
        }
    }

    public Jeu getJeu() {
        return jeu;
    }

    /**
     * Retourne la position de la case
     * @return La position de la case
     */
    public int[] getPos() {
        int[] pos = new int[2];
        pos[0] = this.no % 8 + 1;
        pos[1] = this.no / 8 + 1;
        return pos;
    }

    /**
     * Retourne le pion
     * @return Le pion
     */
    public Pions getPion() {
        return pion;
    }

    /**
     * Permet de choisir un pion et d'effectuer des actions avec les pions
     */
    public void toggleClick() {
        this.jeu.repaint();

        if ((!jeu.isCaseSelect() && pion.isVisible() && pion.getProprio() == jeu.getJoueurActu()) || pion.isSelected()) {
            this.pion.toggleClick();

            jeu.toggleCaseSelect(this);
            jeu.setNextPionRedd(false);
        }

        // On place un pion
        if (!this.pion.isVisible() && jeu.isCaseSelect() && isInRange()) {
            if (getDistance() == 2) {
                if (jeu.getCaseSelect().getPion().isSuperPions()) {
                    jeu.getCaseSelect().getPion().setSuperPions(false);
                }
                jeu.getCaseSelect().getPion().setVisible(false);

            }
            this.pion.setProprio(jeu.getJoueurActu());
            this.pion.setVisible(true);

            if (jeu.isNextPionRedd()) {
                this.pion.setSuperPions(true);
                jeu.setSuperReddUsed();
                jeu.setNextPionRedd(false);
            }


            this.volePionProche();
            this.jeu.finiTour();
        }
        this.jeu.update();

    }

    /**
     * Retourne si le mouvement voulu est accessible avec le pion choisi
     * @return Si la case est dans la portée
     */
    private boolean isInRange() {
        if (this.jeu.getCaseSelect() == this) {
            return false;
        }
        int[] posThis = this.getPos();
        int[] posSource = jeu.getCaseSelect().getPos();
        if (!(posSource[0] + 2 >= posThis[0] && posSource[0] - 2 <= posThis[0]) || !(posSource[1] + 2 >= posThis[1] && posSource[1] - 2 <= posThis[1])) {
            return false;
        }
        return true;
    }

    /**
     * Retourne la distance entre la position finale et initiale
     * @return La distance
     */
    private int getDistance() {
        if (!isInRange()) {
            return 0;
        }

        int[] posThis = this.getPos();
        int[] posSource = jeu.getCaseSelect().getPos();
        int disX = Math.abs(posThis[0] - posSource[0]);
        int disY = Math.abs(posThis[1] - posSource[1]);
        if (disX == 2 || disY == 2) {
            return 2;
        } else {
            return 1;
        }
    }

    /**
     * Permet de voler les pions adverses lors des déplacements du pion
     */
    private void volePionProche() {
        int[] posThis = this.getPos();
        for (int i = (posThis[0] - 1); i <= (posThis[0] + 1); i++) {
            for (int j = (posThis[1] - 1); j <= (posThis[1] + 1); j++) {
                if (!(i == posThis[0] && j == posThis[1]) && i >= 1 && j >= 1 && i <= 8 && j <= 8) {
                    if (!jeu.getCase(i, j).getPion().isSuperPions()) {
                        if (this.pion.isSuperPions() && jeu.getCase(i, j).getPion().getProprio() != jeu.getJoueurActu()) {
                            jeu.getCase(i, j).getPion().setSuperPions(true);
                        }
                        jeu.getCase(i, j).setPionProprio(jeu.getJoueurActu());
                    }
                }
            }
        }
    }

    /**
     * Permet de déterminer la couleur des cases
     */
    private void setCouleur() {
        if (isCouleur) {
            this.couleur = new Color(82, 208, 23);
        } else {
            this.couleur = new Color(52, 124, 44);
        }

        this.setBackground(couleur);

    }

    /**
     * Classe qui permet de gérer les évènements de la classe Cases
     */
    public class GererEvenement extends MouseAdapter implements Serializable {

        /**
         * Change la couleur de la case quand le curseur la pointe
         * @param e
         */
        @Override
        public void mouseEntered(MouseEvent e) {
            setBackground(Color.GRAY);
        }

        /**
         * La case redevient normale lorsque le curseur sort de la case
         * @param e
         */
        @Override
        public void mouseExited(MouseEvent e) {
            setBackground(couleur);
        }

        /**
         * Gère la sélection des pions avec la souris
         * @param e
         */
        @Override
        public void mousePressed(MouseEvent e) {
            toggleClick();
        }
    }
}
